package com.donn.securitycontrolplatform.utils;

import java.awt.geom.Point2D;
import java.util.List;

public class ElefenceAlgorithm {
    /**
     * 判断该点是否在区域内
     * 说明：该点出发的射线模拟为向左射出的水平射线
     *
     * @param pointList
     * @param point
     * @return
     */
    public static Boolean isInArea(List<Point2D.Double> pointList, Point2D.Double point) {
        Boolean flag = true; //是否在区域内标识
        Point2D.Double p, p1, p2;
        Integer across = 0; //穿越次数
        double precision = 2e-10; //浮点类型计算时候的比较容差
        p = point;

        for (int i = 0; i < pointList.size(); i++) {
            p1 = pointList.get(i);
            int j = (i + 1) >= pointList.size() ? 0 : (i + 1);
            p2 = pointList.get(j);
            // 1、判断是否在点上
            if (p1.equals(p) || p2.equals(p)) {
                return flag;
            }
            // 2、该点是否在两个端点之间
            if (p.y <= Math.max(p1.y, p2.y) && p.y >= Math.min(p1.y, p2.y)) {
                // 3、判断该点是否在两点连成的线段上
                if (p.x <= Math.max(p1.x, p2.x) && p.x >= Math.min(p1.x, p2.x)) {
                    // 其一：该线段是水平线
                    if (p1.y == p2.y) {
                        if (p.y == p1.y) {
                            return flag;
                        }
                    }
                    // 其二：该线段是垂直线
                    if (p1.x == p2.x) {
                        if (p.x == p1.x) {
                            return flag;
                        }
                    }
                    // 其三：该线段是斜线
                    double xianShangY = p1.y + (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x);
                    if (Math.abs(xianShangY - p.y) < precision) {
                        // 在线上
                        return flag;
                    }
                }
                // 4、判断两个端点是否越过该点（因为是左水平射线）
                if (p.x <= Math.min(p1.x, p2.x)) {
                    continue;
                }
               /*
                    该点位于两个端点之间，判断是否穿过顶点（穿过顶点时，顶点按照在射线上部处理）
                    穿过顶点时，只有两个端点在射线两侧的才按照穿越处理
                */
                if (p1.y != p2.y && p.y != Math.min(p1.y, p2.y)) {
                    across++;
                }
            }
        }
        if (across % 2 == 0) {
            // 偶数，在外部
            return !flag;
        }
        return flag;
    }

}